#include "SList.h"

void SLTPrint(SLTNode* phead)
{
    SLTNode* pcur = phead;
    while (pcur)
    {
        printf("%d -> ", pcur->data);
        pcur = pcur->next;
    }
    printf("NULL\n");
}

SLTNode* SLTbuyNode(SLTDataType x)
{
    SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
    if (newnode == NULL)
    {
        perror("malloc fail!");
        exit(1);
    }
    newnode->data = x;
    newnode->next = NULL;
    newnode->prev = NULL; 
    return newnode;
}

void SLTPushBack(SLTNode** pplist, SLTNode** pphead, SLTDataType x)
{
    assert(pplist && pphead);
    SLTNode* newnode = SLTbuyNode(x);
    if (*pplist == NULL || *pphead == NULL)
    {
        *pphead = newnode;
        *pplist = newnode;
    }
    else {
        (*pplist)->next = newnode;
        newnode->prev = *pplist; 
        *pplist = newnode;
    }
}

void SLTPushFront(SLTNode** pphead, SLTNode** pplist, SLTDataType x)
{
    assert(pplist && pphead);
    SLTNode* newnode = SLTbuyNode(x);
    if (*pplist == NULL && *pphead == NULL)
    {
        *pphead = newnode;
        *pplist = newnode;
    }
    else
    {
        (*pphead)->prev = newnode; 
        newnode->next = *pphead;
        *pphead = newnode;
    }
}

void SLTPopBack(SLTNode** pplist, SLTNode** pphead)
{
    assert(pplist && *pplist);
    if ((*pplist)->prev == NULL) 
    {
        free(*pplist);
        *pphead = NULL;
        *pplist = NULL;
    }
    else
    {
        SLTNode* tem = *pplist;
        *pplist = (*pplist)->prev; 
        free(tem);
        tem = NULL;
        (*pplist)->next = NULL;
    }
}

void SLTPopFront(SLTNode** pplist, SLTNode** pphead)
{
    assert(pphead && *pphead);
    if ((*pphead)->next == NULL) 
    {
        free(*pphead);
        *pphead = NULL;
        *pplist = NULL;
    }
    else
    {
        SLTNode* next = (*pphead)->next;
        free(*pphead);
        *pphead = next;
        (*pphead)->prev = NULL;
    }
}

int SLTCount(SLTNode* phead)
{
    int count=0;
    while (phead)
    {
        count++;
        phead = phead->next;
    }
    return count;
}

void SLTInsert(SLTNode** pphead, SLTNode** pplist, int pos, SLTDataType x)
{
    assert(pphead && pplist);
    int count = SLTCount(*pphead);
    assert(pos > 0 && pos <= count + 1);
    SLTNode* tem = *pphead;
    for (int i = 1; i < pos; i++)
    {
        tem = tem->next;
    }
    if (tem == *pphead)
    {
        SLTPushFront(pphead, pplist, x);
    }
    else if (tem == *pplist)
    {
        SLTPushBack(pplist, pphead, x);
    }
    else
    {
        SLTNode* newnode = SLTbuyNode(x);
        newnode->next = tem;
        tem->prev->next = newnode;
        newnode->prev = tem->prev;
        tem->prev = newnode;
    }
}

SLTNode* SLTFind(SLTNode* pphead, SLTDataType x)
{
    assert(pphead);
    SLTNode* tem = pphead;
    if (tem->data == x)
    {
        return pphead;
    }
    while ((tem = tem->next)!=NULL)
    {
        if (tem->data == x)
        {
            return tem;
        }
    }
    return NULL;
}

void SLTErase(SLTNode** pphead, SLTNode** pplist, int pos)
{
    assert(pphead && pplist);
    int count = SLTCount(*pphead);
    assert(pos > 0 && pos <= count);
    SLTNode* tem = *pphead;
    for (int i = 1; i < pos; i++)
    {
        tem = tem->next;
    }
    if (tem == *pphead)
    {
        SLTPopFront(pphead, pplist);
    }
    else if (tem == *pplist)
    {
        SLTPopBack(pplist, pphead);
    }
    else
    {
        tem->prev->next = tem->next;
        tem->next->prev = tem->prev;
        free(tem);
        tem = NULL;
    }
}

